/******************************************************************************
 * * hal_wlan.h - implementation of wlan interface
 *
 * *(C) Copyright 2020 Asr International Ltd.
 * * All Rights Reserved
 * ******************************************************************************/

#ifndef HAL_WLAN_H_
#define HAL_WLAN_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "hal.h"
#include "lv_conf.h"

#if USE_LV_WLAN != 0

#define HAL_WLAN_MAX_SSID_LEN                      32
#define HAL_WLAN_MAX_PWD_LEN                       64
#define HAL_WLAN_MIN_WPA_PWD_LEN                   8
#define HAL_WLAN_MIN_WEP_PWD_LEN                   5
#define HAL_WLAN_MAX_BSSID_LEN                     6

enum {
    HAL_WLAN_SIGNAL_STRENGTH_NO = 0,
    HAL_WLAN_SIGNAL_STRENGTH_POOR,
    HAL_WLAN_SIGNAL_STRENGTH_FAIR,
    HAL_WLAN_SIGNAL_STRENGTH_GOOD,
    HAL_WLAN_SIGNAL_STRENGTH_EXCELLENT,
};
typedef uint8_t HAL_WLAN_SIGNAL_STRENGTH_T;

/* not support open and scan ap at the same time */
enum {
    HAL_WLAN_STATE_INIT = 0,
    HAL_WLAN_STATE_ON,
    HAL_WLAN_STATE_SCAN,
    HAL_WLAN_STATE_OPEN_SPEC,
    HAL_WLAN_STATE_OPEN_AUTO,
    HAL_WLAN_STATE_DEINIT,
    HAL_WLAN_STATE_OPEN_NW_WITHOUT_SECURITY,
};
typedef uint8_t HAL_WLAN_STATE_T;

enum {
    HAL_WLAN_AP_STATE_SAVED = 0,
    HAL_WLAN_AP_STATE_ACT,
    HAL_WLAN_AP_STATE_OPENING,
    HAL_WLAN_AP_STATE_GETTING_IP,
    HAL_WLAN_AP_STATE_OPEN_FAILED,
    HAL_WLAN_AP_STATE_PASSWORD_ERROR,
    HAL_WLAN_AP_STATE_NO_INTERNET,
    HAL_WLAN_AP_STATE_RETRY, /* the ap disconnected by lower layer is still scanned for a moment,
                              * it is possible to connect the ap again,
                              * not show to user for the uncertain connecting process */
};
typedef uint8_t HAL_WLAN_AP_STATE_T;

enum {
    HAL_WLAN_SECURITY_OPEN = 0,               //NONE
    HAL_WLAN_SECURITY_WEP,                    //WEP
    HAL_WLAN_SECURITY_WPA,                    //WPA
    HAL_WLAN_SECURITY_WPA2,                   //WPA2
    HAL_WLAN_SECURITY_WPA_WPA2,               //WPA or WPA2
    HAL_WLAN_SECURITY_UNSPECIFIED,            //not specify security for wifi set by client app
    HAL_WLAN_SECURITY_MAX = HAL_WLAN_SECURITY_UNSPECIFIED,
};
typedef uint8_t HAL_WLAN_SECURITY_T;

typedef struct {
    char ssid[HAL_WLAN_MAX_SSID_LEN + 1];
    HAL_WLAN_SECURITY_T security;
    int8_t power;                           /* Rssi strength, min:-127, max:-20. */
} hal_wlan_ap_t;

typedef struct {
    char ssid[HAL_WLAN_MAX_SSID_LEN + 1];
    char pwd[HAL_WLAN_MAX_PWD_LEN + 1];
    HAL_WLAN_SECURITY_T security;
} hal_wlan_nw_t;

typedef struct {
    HAL_WLAN_AP_STATE_T state;
    hal_wlan_nw_t * nw;
    int8_t power;                           /* Rssi strength, min:-127, max:-20. */
    bool is_hidden;
    uint8_t pwd_err_num;                    /* the number of password error in one-time connectivity */
    uint8_t try_num;                        /* the try times in one-time connectivity */
    uint8_t conn_num;                       /* the times of connectivity */
    HAL_WLAN_SECURITY_T alt_security;       /* valid if security for nw is HAL_WLAN_SECURITY_UNSPECIFIED */
} hal_wlan_saved_ap_t;

typedef struct {
    hal_wlan_saved_ap_t * ap;
    HAL_WLAN_AP_STATE_T proc_state;         /* not for ui display */
    bool is_first;                          /* Not save the network if opening failed at the first
                                             * time because of password error */
} hal_wlan_process_t;

typedef struct {
    HAL_WLAN_STATE_T state;
    HAL_WLAN_STATE_T next_state;
    lv_ll_t saved_ap_list;                  /* hal_wlan_saved_ap_t, ap with network */
    lv_ll_t scan_list;                      /* hal_wlan_ap_t, ap without network */
    hal_wlan_process_t proc;                /* for active or opening ap */
    hal_wlan_saved_ap_t * last_act_ap;
    hal_wlan_saved_ap_t * last_disc_ap;
    bool is_auto_sel_nw;                    /* select WLAN intelligently when WLAN connection is poor if true */
    char ip[16];
    int8_t hid_ap_power[HAL_WLAN_SECURITY_MAX]; /* no hidden ap if 0 */
    hal_wlan_nw_t * opening_nw;
} hal_wlan_info_t;

enum {
    HAL_WLAN_EVENT_UPDATE_AP_LIST = 0,     /* update for starting to scan, scanning result, opening successfully or failed */
    HAL_WLAN_EVENT_START_SCAN,
    HAL_WLAN_EVENT_STOP_SCAN_ABNORMAL,
    HAL_WLAN_EVENT_UPDATE_ACT_AP_RSSI,
    HAL_WLAN_EVENT_OPEN_WLAN_FAILURE,
    HAL_WLAN_EVENT_GETTING_IP,
    HAL_WLAN_EVENT_WLAN_OPENED,
    HAL_WLAN_EVENT_WLAN_CLOSED,
    HAL_WLAN_EVENT_OPEN_FAILED_WITH_PASSWORD_ERROR,
    HAL_WLAN_EVENT_NO_INTERNET,
};
typedef uint8_t HAL_WLAN_EVENT_T;

typedef struct {
    uint8_t cmd; /* add wifi network if 1, delete wifi network if 0 */
    char ssid[HAL_WLAN_MAX_SSID_LEN + 1];
    char pwd[HAL_WLAN_MAX_PWD_LEN + 1];
} hal_wlan_wifi_info_t;

enum {
    HAL_WLAN_HW_RESET_PHASE_NULL = 0, // hw reset is not started or is over
    HAL_WLAN_HW_RESET_PHASE_CLOSE,    // waiting for sdio_wifi_open
    HAL_WLAN_HW_RESET_PHASE_OPEN,     // waiting for wlan_wifi_open after sdio_wifi_open
};
typedef uint8_t HAL_WLAN_HW_RESET_PHASE_T;

typedef void (*HAL_WLAN_EVENT_CB)(HAL_WLAN_EVENT_T event);
typedef bool (*HAL_WLAN_GET_LCD_STATUS_CB)(void);
typedef bool (*HAL_WLAN_GET_CM_CONN_SETTING_CB)(void);
#if USE_LV_BLUETOOTH != 0
typedef bool (*HAL_WLAN_OPEN_BT_WITHOUT_UI_CB)(void);
#endif

void hal_wlan_config(void);

/* api for ui, hal wlan will not memfree the input pointer */
void hal_wlan_init(bool is_flight_mode, HAL_WLAN_GET_LCD_STATUS_CB status_cb,
                   HAL_WLAN_EVENT_CB event_cb);
void hal_wlan_ui_state_chg(bool in_wlan_ui);
hal_wlan_info_t * hal_wlan_get_info(void);
lv_ll_t * hal_wlan_get_nw_list(void); // the structure of node is hal_wlan_nw_t
HAL_WLAN_SIGNAL_STRENGTH_T hal_wlan_get_rssi_level(void);
void hal_wlan_lcd_wakeup(bool onoff);
HAL_WLAN_SIGNAL_STRENGTH_T hal_wlan_rssi_level_calc(int8_t rssi);
void hal_wlan_get_cm_conn_setting_cb_reg(HAL_WLAN_GET_CM_CONN_SETTING_CB cb);
bool hal_wlan_is_connected_state(void);
uint8_t hal_wlan_get_min_pwd_len(HAL_WLAN_SECURITY_T security);

/* set wifi from setting ui start */
void hal_wlan_reset(void);
bool hal_wlan_ui_open_wlan(void);
bool hal_wlan_ui_close_wlan(void);
bool hal_wlan_ui_scan_ap(void);
bool hal_wlan_ui_open_ap(char * ssid, HAL_WLAN_SECURITY_T security, char * new_pwd);
bool hal_wlan_ui_del_saved_nw(char * ssid, HAL_WLAN_SECURITY_T security);
bool hal_wlan_ui_add_nw(hal_wlan_nw_t * nw);
bool hal_wlan_ui_set_auto_sel_nw(bool is_auto);
void hal_wlan_ui_open_flight_mode(void);
void hal_wlan_ui_close_flight_mode(void);
/* set wifi from setting ui end */

/* set wifi from client app start */
void hal_wlan_set_wifi_ind(hal_wlan_wifi_info_t * info);
/* set wifi from client app end */

#if USE_LV_BLUETOOTH != 0
bool hal_wlan_delay_to_start_bt(HAL_WLAN_OPEN_BT_WITHOUT_UI_CB cb);
extern bool wlan_bt_firmware_assert(void);
extern bool wlan_bt_recover_connection_fw_assert(void);
#endif

#ifdef BUILD_IN_PC_SIMULATOR
#define OSA_TICK_FREQ_IN_MILLISEC   5   /* Tick frequency for the OS.      */
// 1 ticks = 5ms
#define MS_TO_TICKS(n) ((n) / OSA_TICK_FREQ_IN_MILLISEC ? (n) / OSA_TICK_FREQ_IN_MILLISEC : 1)
uint8_t uos_timer_create(void **pptimer);
uint8_t uos_timer_start(void *ptimer, uint32_t ticks, uint32_t repeaticks,
                        void (*callback)(uint32_t), uint32_t param);
uint8_t uos_timer_delete(void *ptimer);
typedef void (*PTASK_ENTRY)(void * pParameter);
TASK_HANDLE *uos_create_task(PTASK_ENTRY pTaskEntry, void *pParameter, uint16_t nMsgQSize,
                             uint32_t nStackSize, uint8_t nPriority, const char *pTaskName);
#endif

#endif /*USE_LV_WATCH_WLAN*/
#ifdef __cplusplus
}
#endif

#endif/*HAL_WLAN_H_*/
